package main

import (
	"encoding/binary"
	"encoding/json"
	"flag"
	"fmt"
	"net"
	"proto"
	"sync"
)

var toChan chan string

func init() { // 每个文件会自动执行的函数
	flagStart()
	toChan = make(chan string,1)
}

func main() {
	flag.Parse()
	if register.name!=""{

		reg:=proto.RegCmd{}
		reg.Cmd.Cmd="RegCmd"
		reg.NickName=register.name
		reg.Password=register.pwd
		reg.Sex=register.sex

		err:=writeUnix(reg)
		if err!=nil {
			fmt.Println(err)
			return
		}
		return
	}
	if login.name!=""{

		reg:=proto.LoginCmd{}
		reg.Cmd.Cmd="LoginCmd"
		reg.NickName=login.name
		reg.Password=login.pwd

		err:=writeUnix(reg)
		if err!=nil {
			fmt.Println(err)
			return
		}
		return
	}
	if msg.to!=""{


		reg:=proto.Msg{}
		reg.Cmd.Cmd="Msg"
		reg.To=msg.to

		err:=writeUnix(reg)
		if err!=nil {
			fmt.Println(err)
			return
		}
		return
	}

	if list {
		cmd:=proto.Cmd{}
		cmd.Cmd="UserList"
		err:=writeUnix(cmd)
		if err!=nil {
			fmt.Println(err)
			return
		}
		return
	}

	//其他协议不通过则监听
	wg := sync.WaitGroup{}
	wg.Add(2)
	go listenUnix(&wg)
	go listenTcp(&wg)
	wg.Wait()
}
func writeUnix(cmd interface{})error{
	port := "47888"
	dial, err := net.Dial("unix","127.0.0.1:"+port)
	if err != nil {
		return err
	}
	defer func(dial * net.Conn) {
		_=(*dial).Close()
	}(&dial)
	bytes,err :=json.Marshal(cmd)
	if err != nil {
		return err
	}
	bytesLen := len(bytes)
	err=binary.Write(dial,binary.LittleEndian,int32(bytesLen))
	if err != nil {
		return err
	}

	_,err = dial.Write(bytes)
	return err
}
func listenUnix(group *sync.WaitGroup) {
	defer func() {
		group.Done()
	}()
	port := "47888"
	listen, err := net.Listen("unix", "127.0.0.1:"+port)
	if err != nil {
		fmt.Println("本地"+port+"输入端口被占用 err", err)
		return
	}
	for {
		UnixConn, err := listen.Accept()
		if err != nil {
			fmt.Println("本地Accept err", err)
			continue
		}
		go func(UnixConn *net.Conn) {
			defer func() {
				(*UnixConn).Close()
			}()

			var cmdLen int32
			err:=binary.Read(*UnixConn,binary.LittleEndian,&cmdLen)
			if err!=nil{
				fmt.Println("unix链接断开 err",err)
				return
			}
			b:=make([]byte, cmdLen)
			_,err =(*UnixConn).Read(b)
			if err!=nil{
				fmt.Println("链接断开 err",err)
				return
			}
			toChan<-string(b)
		}(&UnixConn)
	}
}
func listenTcp(group *sync.WaitGroup) {
	defer func() {
		group.Done()
	}()

	conn, err := net.Dial("tcp", "localhost:48888")
	if err != nil {
		fmt.Println("无法监听",err)
		return
	}

	//读取
	go func(conn *net.Conn) {
		for{
			var cmdLen int32
			err:=binary.Read(*conn,binary.LittleEndian,&cmdLen)
			if err!=nil{
				fmt.Println("链接断开 err",err)
				return
			}
			b:=make([]byte, cmdLen)
			_,err =(*conn).Read(b)
			if err!=nil{
				fmt.Println("链接断开 err",err)
				return
			}
			//TODO 解析协议后打印到标准输出
			err= handle(b)
			if err!=nil {
				fmt.Println("协议解析错误 err:",err)
			}

		}
	}(&conn)
	//写入
	go func(conn *net.Conn) {
		for{
			//unix socket 接收协议
			cmd:=<-toChan
			bytes := ([]byte)(cmd)

			err:=binary.Write(*conn,binary.LittleEndian, int32(len(cmd)))
			if err!=nil{
				fmt.Println("链接断开 err",err)
				return
			}
			_,err =(*conn).Write(bytes)
			if err!=nil{
				fmt.Println("链接断开 err",err)
				return
			}
		}
	}(&conn)

}
